home *** CD-ROM | disk | FTP | other *** search
- /* Usermount.c : build over the Peter Orbaek mount, just only cutting here
- and there by Romano Giannetti. It permits to normal users mount devices
- the superuser list in /etc/ufstab. It admit multiple entry with different
- fs-type and equal device and directory (see the exemple for /floppy)
- */
-
- /*
- mount.c - A better mount command for Linux 0.99-patchlevel 8 or later.
- by Peter Orbaek <poe@daimi.aau.dk>
-
- Copyright (C) 1992,93 Peter Orbaek.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
- #define _BSD_SOURCE
- #define _POSIX_SOURCE
- #include <stdio.h>
- #include <errno.h>
- #include <unistd.h>
- #include <fcntl.h>
- #include <mntent.h>
- #include <getopt.h>
- #include <string.h>
- #include <errno.h>
- #include <sys/stat.h>
- #include <sys/mount.h>
- #include <sys/types.h>
-
-
- /*#define _LINUX_TYPES_H*/
- #include <linux/fs.h>
-
- /* these really should be defined in <mntent.h>. */
- #define MNTOPT_NODEV "nodev"
- #define MNTOPT_NOEXEC "noexec"
- #define MNTOPT_SYNC "sync"
-
- #ifndef __STDC__
- #error Error: This program requires ANSI C to compile
- #endif
-
- #define MTAB_FILE MOUNTED
- #define LOCK_FILE "/etc/mtab~"
-
- #define UFSTAB "/etc/ufstab"
-
- int opt_mountall = 0;
- int opt_print = 0;
- int opt_verbose = 0;
- int opt_std = 0;
- int opt_usermount= 0;
- int opt_fakemtab = 0;
- int opt_nomtab = 0;
- int opt_type = 0;
-
- char opt_nostd[200];
- char mntoptions[200] = "defaults";
-
- char mnttype[MNTMAXSTR] = "";
- char *mntdev = NULL, *mntdir = NULL;
- char mntdevbuf[MNTMAXSTR];
-
- void usage(), process_options(char *opts);
- void err(char *str);
- void print_mtab(char *);
- int do_mount(struct mntent *);
- int lock_mtab();
- void unlock_mtab();
- void print_mntent(struct mntent *);
-
- void usage()
- {
- fprintf(stderr,
- "Usage: usermount [-fnprv] [-t type] [-o options] [[dev] dir]\n");
-
- err(NULL);
- }
-
- int main(int argc, char *argv[])
- {
- char c;
-
- /* parse options */
-
- while((c = getopt(argc, argv, "fnpt:rvo:")) != EOF) {
- switch(c) {
- case 'p':
- opt_print = 1;
- break;
- case 't':
- strncpy(mnttype, optarg, MNTMAXSTR-1);
- opt_type=1;
- break;
- case 'r':
- if(mntoptions[0] != '\0') strcat(mntoptions, ",");
- strcat(mntoptions, "ro");
- break;
- case 'v':
- opt_verbose = 1;
- break;
- case 'o':
- strncpy(mntoptions, optarg, sizeof(mntoptions)-1);
- break;
- case 'f':
- opt_fakemtab = 1;
- break;
- case 'n':
- opt_nomtab = 1;
- break;
- default:
- usage();
- }
- }
-
- opt_usermount = 1; /* RGtti: only usermount */
-
- if(optind < argc) {
- mntdev = argv[optind++];
- if(optind >= argc) {
- char *filename = UFSTAB;
- FILE *fstab;
- struct mntent *mp;
-
-
- /* only a mount-point was given, look up device in fstab */
- mntdir = mntdev; mntdev = NULL;
-
- if(!(fstab = setmntent(filename, "r"))) err(filename);
- while((mp = getmntent(fstab))) {
- if( (!strcmp(mntdir, mp->mnt_dir)) &&
- (!strcmp(mnttype, mp->mnt_type) || !opt_type) ) {
- strncpy(mntdevbuf, mp->mnt_fsname, sizeof(mntdevbuf)-1);
- mntdev = mntdevbuf;
- break;
- } else if( (!strcmp(mntdir, mp->mnt_fsname)) &&
- (!strcmp(mnttype, mp->mnt_type) || !opt_type)) {
- strncpy(mntdevbuf, mp->mnt_dir, sizeof(mntdevbuf)-1);
- mntdev = mntdir;
- mntdir = mntdevbuf;
- }
- }
- endmntent(fstab);
-
- if(!mntdev) {
- fprintf(stderr, "mount: Don't know what to mount on %s\n",
- mntdir);
- err(NULL);
- }
- } else mntdir = argv[optind];
-
- } else if(argc == 1) {
- /* with no args, just print mtab */
- print_mtab(MTAB_FILE);
- unlock_mtab();
- exit(0);
- }
-
- /* done with the arguments, now do some work */
-
- if(geteuid()) {
- fprintf(stderr, "usermount: I have to be installed setuid root!.\n");
- err(NULL);
- }
-
- /* check for lock */
- if(!lock_mtab()) {
- /* don't use err() for this */
- fprintf(stderr, "usermount: A lock-file exists, mount denied.\n");
- exit(1);
- }
-
- if(mntdir) {
- struct mntent mnt;
-
- if(opt_usermount) {
- FILE *fstab;
- struct mntent *mp;
- int flag = 0;
-
- if(!(fstab = setmntent(UFSTAB, "r"))) err(UFSTAB);
- while((mp = getmntent(fstab))) {
- if(!strcmp(mntdev, mp->mnt_fsname)
- && !strcmp(mntdir, mp->mnt_dir)
- && (!strcmp(mnttype, mp->mnt_type) || !opt_type) ) {
- flag = 1;
- strncpy(mntoptions, mp->mnt_opts, sizeof(mntoptions)-1);
- strncpy(mnttype, mp->mnt_type, sizeof(mnttype)-1);
- break;
- }
- }
- endmntent(fstab);
- if(!flag) {
- fprintf(stderr, "usermount: Can't usermount %s.\n", mntdir);
- err(NULL);
- }
- }
-
- mnt.mnt_type = mnttype;
- mnt.mnt_fsname = mntdev;
- mnt.mnt_dir = mntdir;
- mnt.mnt_opts = mntoptions;
- mnt.mnt_freq = 0;
- mnt.mnt_passno = 0;
-
- if(!do_mount(&mnt)) {
- unlock_mtab();
- exit(1);
- }
-
- /* Now set the uid, gid of the mount-point to the user */
-
- chown(mntdir,getuid(),getgid());
- }
-
- unlock_mtab();
-
- exit(0);
- }
-
- int lock_mtab()
- {
- int fd;
-
- if((fd = open(LOCK_FILE, O_WRONLY | O_CREAT | O_EXCL, 0744)) < 0) return 0;
- close(fd);
- return 1;
- }
-
- void unlock_mtab()
- {
- unlink(LOCK_FILE);
- }
-
- int do_mount(struct mntent *mp)
- {
- struct stat s;
- FILE *mtab;
-
- if(!mp->mnt_type || !mp->mnt_type[0]) mp->mnt_type = "minix";
-
- if(!opt_fakemtab) {
- /* check the directory */
- if(stat(mp->mnt_dir, &s) < 0) {
- if(errno == ENOENT || errno == ESRCH) {
- if(mkdir(mp->mnt_dir, 0755) < 0) {
- fprintf(stderr, "usermount: mkdir(%s) failed.\n", mp->mnt_dir);
- return 0;
- }
-
- if(opt_verbose)
- fprintf(stderr, "Made directory: %s\n", mp->mnt_dir);
-
- } else {
- fprintf(stderr, "usermount: stat(%s) failed.\n", mp->mnt_dir);
- return 0;
- }
-
- } else if(!S_ISDIR(s.st_mode)) {
- fprintf(stderr, "usermount: %s already exists, and isn't a directory.\n",
- mp->mnt_dir);
- return 0;
- }
-
- process_options(mp->mnt_opts);
-
- #if 0
- printf("usermount(%s,%s,%s,%x,%s)\n", mp->mnt_fsname, mp->mnt_dir,
- mp->mnt_type, opt_std, opt_nostd);
- #endif
-
- if(strcmp(mp->mnt_dir, "/") == 0) {
- if(opt_verbose)
- fprintf(stderr, "usermount: root already mounted by kernel\n");
- } else {
- if(strcmp(mp->mnt_type, MNTTYPE_IGNORE) == 0) {
- if(opt_verbose)
- fprintf(stderr, "usermount: ignored %s\n", mp->mnt_fsname);
- return 1;
- }
-
- if(strcmp(mp->mnt_type, MNTTYPE_SWAP) == 0) {
- fprintf(stderr,"usermount: normal user cannot add swap\n");
- return 1;
- } else {
- if(mount(mp->mnt_fsname, mp->mnt_dir, mp->mnt_type,
- 0xc0ed0000|opt_std, opt_nostd) < 0) {
- fprintf(stderr, "usermount: mount(%s,%s) failed: %s\n",
- mp->mnt_fsname, mp->mnt_dir, strerror(errno));
- return 0;
- }
- if(opt_verbose)
- fprintf(stderr, "Mounted %s on %s.\n", mp->mnt_fsname,
- mp->mnt_dir);
- }
- }
- } /* if(!opt_fakemtab) */
-
- if(!opt_nomtab) {
- if(!(mtab = setmntent(MTAB_FILE, "a"))) {
- fprintf(stderr, "usermount: open(%s) failed.\n", MTAB_FILE);
- return 1;
- }
- addmntent(mtab, mp);
-
- endmntent(mtab);
- }
-
- return 1;
- }
-
- void err(char *str)
- {
- if(str) fprintf(stderr, "usermount: %s: %s\n", str, strerror(errno));
-
- if(access(LOCK_FILE, 0) == 0) unlink(LOCK_FILE);
- exit(1);
- }
-
- void print_mntent(struct mntent *mp)
- {
- printf("%s\t%s\t%s\t%s\t%d\t%d\n", mp->mnt_fsname, mp->mnt_dir,
- mp->mnt_type, (mp->mnt_opts[0] == 0) ? "defaults" : mp->mnt_opts,
- mp->mnt_freq, mp->mnt_passno);
- }
-
- void print_mtab(char *filename)
- {
- FILE *mf;
- struct mntent *mp;
-
- if(!((mf = setmntent(filename, "r")))) err(filename);
- while((mp = getmntent(mf))) print_mntent(mp);
- endmntent(mf);
- }
-
-
- void process_options(char *opts)
- {
- /* opts is a comma-separated list of options */
- char opt[MNTMAXSTR];
- char *p;
-
- opt_nostd[0] = '\0';
- opt_std = 0;
-
- while(opts && *opts) {
- for(p = opt; *opts && *opts != ','; *p++ = *opts++);
- *p = '\0';
- if(*opts == ',') opts++;
-
- /* standard options, should be supported by all filesystems */
- if(!strcmp(opt, MNTOPT_DEFAULTS)) {
- if(opt_usermount)
- opt_std = MS_NOSUID|MS_NODEV|MS_NODEV|MS_NOEXEC;
- else
- opt_std = 0;
- }
- else if(!strcmp(opt, MNTOPT_RO)) opt_std |= MS_RDONLY;
- else if(!strcmp(opt, MNTOPT_RW)) opt_std &= ~MS_RDONLY;
- else if(!strcmp(opt, MNTOPT_SUID)) opt_std &= ~MS_NOSUID;
- else if(!strcmp(opt, MNTOPT_NOSUID)) opt_std |= MS_NOSUID;
- else if(!strcmp(opt, MNTOPT_NODEV)) opt_std |= MS_NODEV;
- else if(!strcmp(opt, MNTOPT_NOEXEC)) opt_std |= MS_NOEXEC;
- else if(!strcmp(opt, MNTOPT_SYNC)) opt_std |= MS_SYNC;
- else {
- /* non-standard options are put in a comma-sep. string */
- strcat(opt_nostd, opt);
- strcat(opt_nostd, ",");
- }
- }
-
- if(opt_nostd[0])
- opt_nostd[strlen(opt_nostd)-1] = '\0';
-
- }
-